package unimelb.distSystems.project2;

import java.io.Serializable;
import java.util.LinkedList;

/*
 * MatchRoom class is an entity type for match room and racing session 
 * Comment on Serializable LinkedList: Standard implementations of List is already serializable
 */
public class MatchRoom implements Serializable {
	private long matchroom_id;
	private String name;
	private LinkedList<String> messages = new LinkedList<String>();
	private int max_players;
	private long host_id;
	private LinkedList<Long> players=new LinkedList<Long>();
	private long track_id;
	private LinkedList<Long> number_ready_players=new LinkedList<Long>();
	private boolean isInRacingProgress=false;
	
	/*
	 * Constructor
	 */
	public MatchRoom(long matchroom_id,String name,int max_players,long track_id)
	{
		this.matchroom_id=matchroom_id;
		this.name=name;
		this.max_players=max_players;
		this.host_id=-1;
		this.track_id=track_id;
		this.isInRacingProgress=false;
	}
	
	/*
	 * Get list of chat messages
	 * Input: Nothing
	 * Output: LinkedList<String> messages
	 */
	public LinkedList<String> getAllMessages()
	{
		return messages;
	}
	
	/*
	 * Get unique ID of match room
	 * Input: Nothing
	 * Output: long value of ID
	 */
	public long getMatchRoomID()
	{
		return matchroom_id;
	}
	
	/*
	 * Get maximum number of players allowed in match room
	 * Input: Nothing
	 * Output: int value of maximum number of players
	 */
	public int getMaxPlayers()
	{
		return max_players;
	}
	
	/*
	 * Get name of the match room, set by host player
	 * Input: Nothing
	 * Output: String name
	 */
	public String getMatchRoomName()
	{
		return name;
	}
	
	/*
	 * Get unique ID of player who hosts this match room
	 * Input: Nothing
	 * Output: long value of player ID
	 */
	public long getHostID()
	{
		return host_id;
	}
	
	/*
	 * Get list of unique IDs of players who are in the match room
	 * Input: Nothing
	 * Output: LinkedList<Long> of IDs
	 */
	public LinkedList<Long> getAllPlayers()
	{
		return players;
	}
	
	/*
	 * Get the unique of track selected by host player
	 * Input: Nothing
	 * Output: long value of Track ID
	 */
	public long getTrackID()
	{
		return track_id;
	}
	
	/*
	 * Get number of players who are ready for racing
	 * Input: Nothing
	 * Output: int value of number of ready players
	 */
	public int getNumReadyPlayers()
	{
		return number_ready_players.size();
	}
	
	/*
	 * Check of the match room is in currently racing
	 * Input: Nothing
	 * Output: Yes or No on players are playing
	 */
	public boolean isInRacingProgress()
	{
		return isInRacingProgress;
	}	
	
	/////////////////////////////
	// SERVER SIDE
	/////////////////////////////
	/*
	 * TO BE USED BY SERVER
	 * Add new player to the match room and notify players via chat logs
	 * Input: long value of unique ID of new player and String driver name of new player
	 * Output: Nothing
	 */
	public void addPlayer(long player_id,String driver_name)
	{
		if(players.size()<=0)//Host player
			host_id=player_id;
		
		players.add(new Long(player_id));
		messages.add(">>"+driver_name+" joined.");
	}
	
	/*
	 * TO BE USED BY SERVER
	 * Remove the player from the match room and notify players via chat logs
	 * Input: long value of unique ID of player and String driver name of new player
	 * Output: Nothing
	 */
	public void removePlayer(long player_id,String driver_name)
	{		
		if(players.size()<=1)
			return;//Don't need to do anything after he is last person to go
		
		for(int i=0;i<players.size();i++)
		{
			Long this_id = players.get(i);
			if(this_id.longValue()==player_id)
			{
				players.remove(i);
				messages.add(">>"+driver_name+" left.");
			}
		}
	}
	
	/*
	 * TO BE USED BY SERVER
	 * Add new message to char log
	 * Input: String message (driver name should be contained in already)
	 * Output: Nothing
	 */
	public void appendMessage(String message)
	{
		messages.add(message);
	}
	
	/*
	 * TO BE USED BY SERVER
	 * Change player status in the match room and notify players via chat logs
	 * Input: long value of unique ID of player and String driver name of new player
	 * Output: Nothing
	 */
	public void updatePlayerForReady(long player_id,String driver_name)
	{
		for(int i=0;i<number_ready_players.size();i++)
		{
			Long this_id = number_ready_players.get(i);
			if(this_id.longValue()==player_id)
				return;//Ready already
		}
		
		number_ready_players.add(new Long(player_id));
		messages.add(">>"+driver_name+" is READY.");
	}
	
	/*
	 * TO BE USED BY SERVER
	 * Change the status of match room so that players outside can see whether room is racing or not 
	 * Input: Yes or No on we are playing
	 * Output: Nothing
	 */
	public void setRacingProgressFlag(boolean flag)
	{
		isInRacingProgress=flag;
	}
	
	/////////////////////////////
	// CLIENT SIDE
	/////////////////////////////
	/*
	 * TO BE USED BY CLIENT
	 * Invoke interface method from server to add new player to this match room
	 * Input: long value of unique ID of player
	 * Output: Nothing
	 */
	public void join(long player_id)
	{
		////////////////////////////////////
		//COBRA COMMUNICATION
		////////////////////////////////////
		//Invoke join(player id) on server
		
		addPlayer(player_id,"Joiner");//TEMP
	}
	
	/*
	 * TO BE USED BY CLIENT
	 * Invoke interface method from server to remove player from match room
	 * Input: long value of unique ID of player
	 * Output: Nothing
	 */
	public void leave(long player_id)
	{
		////////////////////////////////////
		//COBRA COMMUNICATION
		////////////////////////////////////
		//Invoke leave(player_id) on server

		removePlayer(player_id, "Leaver");//TEMP
	}
	
	/*
	 * TO BE USED BY CLIENT
	 * Invoke interface method from server to add new message for match room
	 * Input: String message (driver name should be contained in already)
	 * Output: Nothing
	 */
	public void addMessage(String message)
	{
		////////////////////////////////////
		//COBRA COMMUNICATION
		////////////////////////////////////
		//Invoke addMessage(message,matchroom ID) on server
		//??
		
		appendMessage(message);//TEMP
	}
	
	/*
	 * TO BE USED BY CLIENT
	 * Invoke interface method from server to change player status in match room
	 * Input: long value of unique ID of player
	 * Output: Nothing
	 */
	public void informReady(long player_id)
	{	
		////////////////////////////////////
		//COBRA COMMUNICATION
		////////////////////////////////////
		//Invoke the informReady(player ID, matchroom ID) on the server
		
		updatePlayerForReady(player_id,"LOL");//TEMP
	}
	
	/*
	 * TO BE USED BY CLIENT
	 * Invoke interface method from server to tell the server to initialize the racing session
	 * Also, tell the server to change isInRacingProgress flag to true so that other players can't join 
	 * Input: Nothing
	 * Output: Nothing
	 */
	public void startSession()
	{
		////////////////////////////////////
		//COBRA COMMUNICATION
		////////////////////////////////////
		//????
	}
}
